/*
 * @Author: z.p
 * @Project: Zdotp
 * @Date: 2025年01月14日
 * @Description: 管理actor交互
 */

using System.Reflection;
using Zdotp.Actor.Packet;
using Zdotp.Logs;

namespace Zdotp.Actor.Controller;

public static class ActorControllerManager
{
    private static readonly ZLogger Logger = new("ActorControllerManager");
    private static readonly Dictionary<Type, IActorController> ActorControllers = new();

    public static void LoadAssemblies(List<Assembly> assemblies)
    {
        foreach (var assembly in assemblies)
        {
            foreach (var classType in assembly.GetTypes())
            {
                var baseType = classType.BaseType;
                if (baseType == null) continue;
                if (!baseType.IsGenericType || baseType.GetGenericTypeDefinition() != typeof(ActorController<,>)) continue;
                var arg = baseType.GetGenericArguments();
                if (arg.Length != 2) continue;
                var actorType = arg[0];
                var messageType = arg[1];
                var controller = Activator.CreateInstance(classType);
                
                if (controller is not IActorController iController)
                {
                    Logger.Error($"Load interface {classType.Name} failed.");
                    continue;
                }
                if (!ActorControllers.TryAdd(messageType, iController))
                {
                    Logger.Error($"MessageType {messageType} allows only one actorController to exist.");
                    continue;
                }
                Logger.Info($"register controller : [ actorType: {actorType.Name} , messageType: {messageType.Name} ]");
            }
        }
    }
    public static void Control(Type messageType, ActorBase actor, MessageInfo info, MailObject message)
    {
        if (ActorControllers.TryGetValue(messageType, out var handler))
        {
            handler.Control(actor, info, message);
        }
        else
        {
            Logger.Error($"Controller {messageType} not found.");
        }
        ActorSystem.ReleaseObj(messageType, message);
    }
}